from rest_framework import serializers



# 自定义序列化器
from rest_framework.serializers import ModelSerializer

from auser.models import BookInfo


class BookSerializer(serializers.Serializer):
    #　序列化：
    # 根据模型类来定义
    """
    图书序列化器
    """

    # 定义字段
    # 默认每个字段都会有required=True的选项参数这个参数局势要求前端必须传递字段数据
    # required=False代表可以不用传递参数
    # 空字符与none不同,允许为空allow_null=True需要配合表单数据使用
    id = serializers.IntegerField(read_only=True) # read_only=True表明该字段只参与序列化返回

    btitle = serializers.CharField(max_length=20,min_length=5)
    # bpub_date = serializers.DateField(default="1999-10-10")
    # bread = serializers.IntegerField(min_value=1,max_value=200)
    # bcomment = serializers.IntegerField(write_only=True) # write_only=True表明该字段只参与反序列化返
    # is_delete = serializers.BooleanField(required=False)
    # 定义一个不存在的字段,没有参数write_only=True的时候，序列化器字段必须和模型类一致
    # hname = serializers.CharField(write_only=True)


    # 关联对象嵌套序列化返回　　父表嵌套子表
    # PrimaryKeyRelatedField返回关联对象id值,多个对象
    # heroinfo_set = serializers.PrimaryKeyRelatedField(many=True,read_only=True)
    # StringRelatedField返回关联对象模型中的_str_方法
    # heroinfo_set = serializers.StringRelatedField(many=True)
    # 想在图书中调用，需在图书类之前进行定义
    # heroinfo_set = HeroSerializer(many=True)
    # hero = HeroSerializer(many=True)

    # 自定义验证方法
    # 单一字段验证validate后面要加上字段名
    def validate_btitle(self, attrs):

        if attrs == 'python':
            raise serializers.ValidationError('书名不能为python')

        return attrs
    # 多个字段验证
    def validate(self, attrs):

        if attrs['bread'] > attrs['bcomment']:
            raise serializers.ValidationError('阅读量大于评论量')

        return attrs

    # create名字固定
    def create(self, validated_data):

        """
        封装保存数据业务
        :param validated_data: 接收验证后的数据
        :return:
        """
        book = BookInfo.objects.create(btitle=validated_data['btitle'],
                    bpub_date=validated_data['bpub_date'])
        # 返回保存后的对象
        return book


    def update(self, instance, validated_data):
        """
        封装更新数据业务
        :param instance: 接收更新数据对象
        :param validated_data: 接收验证后的数据
        :return:
        """
        # BookInfo.objects.filter(id=instance.id).update(**validated_data)
        # instance不为空，调用update方法
        instance.btitle = validated_data['btitle']

        instance.save()
        return instance

class HeroSerializer(serializers.Serializer):
    #　序列化：
    # 根据模型类来定义
    """
    英雄序列化器
    """
    hname = serializers.CharField()
    hgender = serializers.IntegerField()
    hcomment = serializers.CharField()
    is_delete = serializers.BooleanField()

    # 关联对象嵌套序列化返回　　子表嵌套父表
    # hbook = serializers.PrimaryKeyRelatedField(read_only=True)
    # hbook = serializers.StringRelatedField()
    hbook = BookSerializer()
"""
book = BookInfo.objects.get(id=1)
book.heroinfo_set.all()
"""


class BookModelSerializer(serializers.ModelSerializer):
    """
    ModelSerializer和原来Serializer的区别
    1.帮助自动生成序列化器字段
    2.帮助实现create方法和update方法
    3.如果在模型里指定了唯一值参数，会帮助实现唯一值验证方法
    """
    # 显示指明字段进行修改(模型中有的字段)
    # bcomment = serializers.IntegerField(max_value=100,min_value=5)
    # # 显示指明字段进行修改(模型中没有的字段,必须添加在fields中)
    # sms_code = serializers.CharField(max_length=6,min_length=6)
    class Meta:
        # 指定哪个模型类生成序列化字段
        model = BookInfo
        # 指定哪些字段生成序列化字段,元组
        fields = ('id','btitle','bpub_date','bread')
        # 生成全部字段
        # fields = "__all__"
        # 取反生成序列化字段
        # exclude = ('btitle',)

        # 给指定的字段增加一个read_only=True的选项参数
        read_only_fields=('bpub_date',)
        # 添加或修改自动生成的选项参数
        extra_kwargs = {
            'bread':{
                'max_value':100,
                'min_value':5,
            },
            'btitle':{
                'max_length':5,
            }
        }















